#pragma once

#include "vtkOpenCVBridge.h"

void vtkOpenCVBridge::vector_cvMatTogpuMat ()
{
	for (std::vector<cv::Mat>::iterator it = m_vectorCVMat.begin(); it!=m_vectorCVMat.end(); ++it)
	{
		cv::Mat temp_Mat = *it;
		cv::cuda::GpuMat temp_GpuMat (temp_Mat);
		m_vectorGPUMat.push_back (temp_GpuMat);
	}
}

void vtkOpenCVBridge::vector_gpuMatToCvMat ()
{
	for (std::vector<cv::cuda::GpuMat>::iterator it = m_vectorGPUMat.begin(); it!=m_vectorGPUMat.end(); ++it)
	{
		cv::Mat temp_Mat (*it); // check this; program is breaking here
		m_vectorCVMat.push_back (temp_Mat);
	}
}

vtkSmartPointer<vtkImageData> vtkOpenCVBridge::OpenCVtoVTK ()
{
	m_imageData->SetExtent(0, m_dimensions[0], 0, m_dimensions[1], 0, m_dimensions[2]);
	m_imageData->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
	//m_imageData->SetScalarTypeToUnsignedChar();
	//m_imageData->Update();

	for (int vol_dim=0; vol_dim<m_dimensions[2]; ++vol_dim)
	{
		for (int i=0; i<m_dimensions[1]; ++i)
		{
			unsigned char* mat_ptr = m_vectorCVMat[vol_dim].ptr<unsigned char>(i);
			for (int j=0; j<m_dimensions[0]; ++j)
				*static_cast<unsigned char*>(m_imageData->GetScalarPointer(j,i,vol_dim)) = mat_ptr[j];
		}
	}
	return m_imageData;
}

std::vector<cv::cuda::GpuMat> vtkOpenCVBridge::VTKtoOpenCV ()
{
	m_imageData->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
	//m_imageData->SetScalarTypeToUnsignedChar();
	//m_imageData->Update();

	for (int vol_dim=0; vol_dim<m_dimensions[2]; ++vol_dim)
	{
		cv::Mat temp_Mat(m_dimensions[1], m_dimensions[0], CV_8UC1);
		for (int i=0; i<m_dimensions[1]; ++i)
		{
			unsigned char* mat_ptr = temp_Mat.ptr<unsigned char>(i);
			for (int j=0; j<m_dimensions[0]; ++j)
				mat_ptr[j] = *static_cast<unsigned char*>(m_imageData->GetScalarPointer(j,i,vol_dim));
		}
		m_vectorCVMat.push_back(temp_Mat);
	}

	vtkOpenCVBridge::vector_cvMatTogpuMat();
	return m_vectorGPUMat;
	//return m_vectorCVMat;
}

cv::Mat vtkOpenCVBridge::vectorToConcat()
{
	m_concat = cv::Mat(m_vectorGPUMat[0]);
	for (int i=1; i<m_vectorGPUMat.size(); ++i)
		cv::hconcat(m_concat, cv::Mat(m_vectorGPUMat[i]), m_concat);

	return m_concat;
}

std::vector <cv::Mat> vtkOpenCVBridge::concatToVector (cv::Mat& input_concat)
{
	//cv::Mat concat_input(input_concat);
	std::vector <cv::Mat> output_vector;
	for (int i=0; i<input_concat.cols; i=i+m_dimensions[0])
	{
		cv::Rect roi = cv::Rect(i, 0, m_dimensions[0], m_dimensions[1]);
		output_vector.push_back(input_concat(roi));
	}
	return output_vector;
}